#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <linux/input.h>

#include "pthread.h"

#define KEYDevice "/dev/input/event4"

#define START 23
#define STOP 22

unsigned int keys_fd;

unsigned int leddisplay[8] = { 24,24,24,24,24,24,24,24 };

unsigned char tube[] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0x89,0xC7,0x8C,0xC8,0xC1,0xA3,0xBF,0x7f,0xFF };
//  0    1       2       3       4      5       6     7       8      9       A      b      C       d       E       F       H      L       P      n      u       o       -       .

//  0    1       2       3       4      5       6     7       8      9       10    11    12     13     14      15     16   17     18     19    20      21     22   23     24

unsigned char addr[] = { 0x80, 0x40,  0x20,  0x10,  0x08,  0x04, 0x02, 0x01 };
//     第1位  第2位  第3位  第4位  第5位  第6位  第7位  第8位
int time_state = 0;

void clear_led(){
    for (int i = 0;i < 8;i++) {
        leddisplay[i] = 24;
    }
}

char key_code(int code) {
    switch (code) {
    case 2:
        return '1';

    case 3:
        return '2';

    case 4:
        return '3';

    case 5:
        return '4';

    case 6:
        return '5';

    case 7:
        return '6';

    case 8:
        return '7';

    case 9:
        return '8';

    case 10:
        return '9';

    case 1:
        return '.';

    case 115:
        return '0';

    case 114:
        return '-';

    default:
        return 'e';
    }
}

int key_value(int code) {
    switch (code) {
    case 2:
        return 1;

    case 3:
        return 2;

    case 4:
        return 3;

    case 5:
        return 4;

    case 6:
        return 5;

    case 7:
        return 6;

    case 8:
        return 7;

    case 9:
        return 8;

    case 10:
        return 9;

    case 1:
        return 23;

    case 115:
        return 0;

    case 114:
        return 22;

    default:
        return 24;
    }
}

int check_value() {
    //小时超过29
    if (leddisplay[0] > 2 || leddisplay[0] < 0) {
        return 0;
    }
    //小时数在24-29
    if (leddisplay[0] == 2 || leddisplay[1] > 3) {
        return 0;
    }
    //第2位不在0-9之间
    if (leddisplay[1] < 0 || leddisplay[1]>9) {
        return 0;
    }
    //第5位不在0-9之间
    if (leddisplay[4] < 0 || leddisplay[4]>9) {
        return 0;
    }
    //第8位不在0-9之间
    if (leddisplay[7] < 0 || leddisplay[7]>9) {
        return 0;
    }
    //分数超过59
    if (leddisplay[3] > 5 || leddisplay[3] < 0) {
        return 0;
    }
    //秒数超过59
    if (leddisplay[6] > 5 || leddisplay[6] < 0) {
        return 0;
    }
    return 7;
}

void key_action(int keystate_current, int keystate_before, int keyvalue) {
    if (keystate_before == 7 && keystate_current != 7) {
        //暂停计时
        time_state = 0;
    }
    else if (keystate_current == 7) {
        //开始计时
        time_state = 1;
    }
    
    if (keystate_current == keystate_before);
    else if (keystate_current == 1 && keystate_before == 0) {
        //0-1
        leddisplay[0] = keyvalue;
    }
    else if (keystate_current == 2 && keystate_before == 1) {
        //1-2
        leddisplay[1] = keyvalue;
    }
    else if (keystate_current == 3 && keystate_before == 2) {
        //2-3
        leddisplay[2] = 22;
        leddisplay[3] = keyvalue;
    }
    else if (keystate_current == 4 && keystate_before == 3) {
        //3-4
        leddisplay[4] = keyvalue;
    }
    else if (keystate_current == 5 && keystate_before == 4) {
        //4-5
        leddisplay[5] = 22;
        leddisplay[6] = keyvalue;
    }
    else if (keystate_current == 6 && keystate_before == 5) {
        //5-6
        leddisplay[7] = keyvalue;
    }
    else if(keystate_current==1&&keystate_before==6){
        //6-1
        clear_led();
        leddisplay[0] = keyvalue;
    }
    else if (keystate_current == 0) {
        //清空屏幕
        clear_led();
    }
    
}

int check_key_state(int keystate_before, int keyvalue) {
    if (keystate_before == 0) {
        if (keyvalue == STOP) {
            return 0;
        }
        else if (keyvalue == START) {
            return keystate_before;
        }
        return 1;
    }
    else if (keystate_before == 1) {
        if (keyvalue == STOP) {
            return 0;
        }
        else if (keyvalue == START) {
            return keystate_before;
        }
        return 2;
    }
    else if (keystate_before == 2) {

        if (keyvalue == STOP) {
            return 0;
        }
        else if (keyvalue == START) {
            return keystate_before;
        }
        return 3;

    }
    else if (keystate_before == 3) {
        if (keyvalue == STOP) {
            return 0;
        }
        else if (keyvalue == START) {
            return keystate_before;
        }
        return 4;
    }
    else if (keystate_before == 4) {
        if (keyvalue == STOP) {
            return 0;
        }
        else if (keyvalue == START) {
            return keystate_before;
        }

        return 5;
    }
    else if (keystate_before == 5) {
        if (keyvalue == STOP) {
            return 0;
        }
        else if (keyvalue == START) {
            return keystate_before;
        }
        return 6;
    }
    else if (keystate_before == 6) {
        if (keyvalue == START) {
            return check_value();
        }
        else if (keyvalue == STOP) {
            return 0;
        }
        return 1;
    }
    else if (keystate_before == 7) {
        if(keyvalue==STOP){
            return 8;
        }
        return 7;
    }
    else if (keystate_before == 8){
        if(keyvalue==START){
            return 7;
        }
        else if(keyvalue==STOP){
            return 0;
        }
        return 8;
    }

}


void* key_input(void* data) {
    int keystate_before = 0;
    int keystate_current = 0;
    while (1) {
        if (read(keys_fd, &t, sizeof(t)) == sizeof(t))
            if (t.type == EV_KEY)
                if (t.value == 0) {
                    keyvalue = key_value(t.code);
                    keystate_current = check_key_state(keystate_before, keyvalue);
                    key_action(keystate_current, keystate_before, keyvalue);
                    keystate_before = keystate_current;
                }
    }
}


void* time_moving() {
    while (1) {
        while (time_state == 1) {
            usleep(1000000);
            if (leddisplay[7] != 9) {
                leddisplay[7]++;
                return 0;
            }
            else {//秒进位
                leddisplay[7] = 0;
                if (leddisplay[6] != 5) {
                    leddisplay[6]++;
                }
                else {//分加一
                    leddisplay[6] = 0;
                    if (leddisplay[4] != 9) {
                        leddisplay[4]++;
                    }
                    else {//分进位
                        leddisplay[4] = 0;
                        if (leddisplay[3] != 5) {
                            leddisplay[3]++;
                        }
                        else {
                            leddisplay[3] = 0;
                            //时加一
                            if (leddisplay[0] != 2 && leddisplay[1] != 9) {
                                leddisplay[1]++;
                            }
                            else if (leddisplay[0] == 2 && leddisplay[1] != 3) {
                                leddisplay[1]++;
                            }
                            else if (leddisplay[0] != 2&& leddisplay[1] == 9) {//时进位
                                leddisplay[1] = 0;
                                leddisplay[0]++;
                            }
                            else {//下一天
                                leddisplay[1] = leddisplay[0] = 0;
                            }
                        }
                    }
                }
            }
        }
        while (state == 0);
    }
}




int main(int argc, char* argv[]) {
    int i, number;
    int mem_fd;
    unsigned char* cpld;
    void* retval;
    void* retval2;
    pthread_t th_key;
    pthread_t th_time;

    keys_fd = open(KEYDevice, O_RDONLY);

    if (keys_fd <= 0) {
        printf("open key device error!\n");
        return 0;
    }

    mem_fd = open("/dev/mem", O_RDWR);

    cpld = (unsigned char*)mmap(NULL, (size_t)0x10, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, mem_fd, (off_t)(0x8000000));

    if (cpld == MAP_FAILED)
        return;

    for (i = 0; i < 8; i++) {
        *(cpld + (0xe6 << 1)) = addr[i];   			//数码管地址  (0xe6<<1)为地址
        *(cpld + (0xe4 << 1)) = tube[24];   			//数码管个位   (0xe4<<1)为地址            数码管灭
    }

    pthread_create(&th_key, NULL, key_input, 0);
    pthread_create(&th_time, NULL, time_moving, 0);

    while (1) {
        for (i = 0; i < 8; i++) {
            *(cpld + (0xe6 << 1)) = addr[i];   			//数码管地址  (0xe6<<1)为地址

            number = leddisplay[i];

            *(cpld + (0xe4 << 1)) = tube[number];   		//数码管个位   (0xe4<<1)为地址

            usleep(1000);
        }
    }

    pthread_join(th_key, &retval);
    pthread_join(th_time, &retval2);

    for (i = 0; i < 8; i++) {
        *(cpld + (0xe6 << 1)) = addr[i];   			//数码管地址  (0xe6<<1)为地址
        *(cpld + (0xe4 << 1)) = tube[24];   		//数码管个位   (0xe4<<1)为地址                数码管灭
    }

    munmap(cpld, 0x10);

    close(mem_fd);

    close(keys_fd);

    return 0;
}